package org.phalanx.server.game;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;

import org.phalanx.map.MapCoordinates;
import org.phalanx.server.PhalanxServer;
import org.phalanx.server.ServerCache.AbstractCacheHandler;
import org.phalanx.server.ServerCache.Cache;
import org.phalanx.server.ServerCache.CacheManager;
import org.phalanx.server.ServerCache.Cacheable;
import org.phalanx.server.ServerCache.QueryObject;
import org.phalanx.server.sql.SQLAction;
import org.phalanx.server.sql.SQLManager;

public class GameMoveCacheHandler implements AbstractCacheHandler {
	public static final String tableName = "gamemovequeue";

	public static final String GAMEID = "gameid";
	public static final String USERID = "userid";
	public static final String ACTIONTYPE = "actiontype";
	public static final String COOR1 = "coordinates1";
	public static final String COOR2 = "coordinates2";
	public static final String ATTRIBUTE = "attribute";
	public static final String ATTR_VALUE = "attributevalue";
	public static final String TURN = "turn";
	public static final String UNIT_ID_1 = "unitid1";
	public static final String UNIT_ID_2 = "unitid2";

	@Override
	public boolean addElementToDB(Cache c, Object newKey, Cacheable newElement) {
		boolean isSuccess = false;

		SQLManager sqlMan = PhalanxServer.getServerInstance().getSQLManager();
		String[] sqlString;

		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();
		PhalanxGameSettings settings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", newKey);

		if (newElement != null && settings != null){
			Integer turnId = settings.getCurrentTurn();
			GameMoveQueue gQueue = (GameMoveQueue)newElement;

			int statementsSize = gQueue.getMoveList(turnId).size();
			int count = 0;

			try {
				if (statementsSize > 0){
					sqlString = new String[statementsSize];
					Iterator<GameMove> i = gQueue.getMoveList(turnId).iterator();

					while (i.hasNext()){
						GameMove oneMove = i.next();

						SQLAction addMovesToDB = new SQLAction(SQLAction.INSERT, tableName);

						addMovesToDB.addField(GAMEID);
						addMovesToDB.addField(USERID);
						addMovesToDB.addField(ACTIONTYPE);
						addMovesToDB.addField(COOR1);
						addMovesToDB.addField(COOR2);
						addMovesToDB.addField(ATTRIBUTE);
						addMovesToDB.addField(ATTR_VALUE);
						addMovesToDB.addField(TURN);
						addMovesToDB.addField(UNIT_ID_1);
						addMovesToDB.addField(UNIT_ID_2);

						addMovesToDB.addValues(gQueue.getId().toString());
						addMovesToDB.addValues(oneMove.getUserId().toString());
						addMovesToDB.addValues(oneMove.getActionType().toString());
						addMovesToDB.addValues(this.convertMapCoordinatesToString(oneMove.getCoordinates1()));

						String mapCoordinates = oneMove.getCoordinates2() == null 
						? null : this.convertMapCoordinatesToString(oneMove.getCoordinates2());

						addMovesToDB.addValues(mapCoordinates);
						addMovesToDB.addValues(oneMove.getAttributeName());
						addMovesToDB.addValues(oneMove.getAttributeValue());
						addMovesToDB.addValues(oneMove.getTurn().toString());
						addMovesToDB.addValues(oneMove.getUnitid1().toString());

						String unit2 = oneMove.getUnitid2() == null ? null : oneMove.getUnitid2().toString();

						addMovesToDB.addValues(unit2);

						sqlString[count++] = addMovesToDB.getActionString();
					}

					for (int x = 0; x < statementsSize; x++){
						sqlMan.insertQuery(sqlString[x]);
					}
				}
			} catch (SQLException se){}
		}


		return isSuccess;
	}

	@Override
	public boolean deleteObjectFromDB(Cache c, Object newKey,
			Cacheable newElement) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public ArrayList<Cacheable> getMultipleObjectsFromDB(Cache c,
			Object newKey, boolean cacheUpdate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Cacheable getObjectFromDB(Cache c, Object newKey, boolean cacheUpdate) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean populateCache(Cache c) {
		boolean isSuccess = false;

		SQLManager sqlMan = PhalanxServer.getServerInstance().getSQLManager();
		ArrayList<QueryObject> results = new ArrayList<QueryObject>();
		CacheManager cacheMgr = PhalanxServer.getServerInstance().getCacheManager();

		QueryObject gameMoveQuery = new QueryObject();
		gameMoveQuery.setInteger(GAMEID, 0);
		gameMoveQuery.setInteger(USERID, 0);
		gameMoveQuery.setInteger(ACTIONTYPE, 0);
		gameMoveQuery.setString(COOR1, "");
		gameMoveQuery.setString(COOR2, "");
		gameMoveQuery.setString(ATTRIBUTE, "");
		gameMoveQuery.setString(ATTR_VALUE, "");
		gameMoveQuery.setInteger(TURN, 0);
		gameMoveQuery.setInteger(UNIT_ID_1, 0);
		gameMoveQuery.setInteger(UNIT_ID_2, 0);

		SQLAction getAllUsers = new SQLAction(SQLAction.SELECT, tableName);
		getAllUsers.addField("*");

		try {
			results = sqlMan.getQuery(getAllUsers.getActionString(), gameMoveQuery);

			for (int i = 0; i < results.size(); i++){
				QueryObject temp = results.get(i);

				Integer gameId = temp.getInteger(GAMEID);

				PhalanxGameSettings gameSettings = (PhalanxGameSettings)cacheMgr.getElement("GameListCache", gameId);

				if (gameSettings != null){
					GameMoveQueue gQueue = (GameMoveQueue)c.get(gameId);
					Integer currentTurn = gameSettings.getCurrentTurn();

					if (gQueue == null){
						gQueue = new GameMoveQueue(gameId);
						c.put(gameId, gQueue);
					}

					Integer gameTurn = temp.getInteger(TURN);

					GameMove gMove = new GameMove();
					gMove.setActionType(temp.getInteger(ACTIONTYPE));
					gMove.setAttributeName(temp.getString(ATTRIBUTE));
					gMove.setAttributeValue(temp.getString(ATTR_VALUE));
					gMove.setTurn(gameTurn);
					gMove.setUserId(temp.getInteger(USERID));
					gMove.setUnitid1(temp.getInteger(UNIT_ID_1));
					gMove.setUnitid2(temp.getInteger(UNIT_ID_2));

					String mapCoor1 = temp.getString(COOR1);
					String mapCoor2 = temp.getString(COOR2);
					if (mapCoor2 != null){
						MapCoordinates c2 = convertStringToMapCoor(mapCoor2);

						if (c2 != null){
							gMove.setCoordinates2(c2);
						}
					}

					if (mapCoor1 != null){
						MapCoordinates c1 = convertStringToMapCoor(mapCoor1);

						if (c1 != null){
							gMove.setCoordinates1(c1);
							gQueue.addMove(gMove);
						}
					}
				} // gameSettings != null
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


		return isSuccess;
	}

	private MapCoordinates convertStringToMapCoor(String mapCoorString){
		MapCoordinates c = null;

		if (mapCoorString.length() > 4){
			mapCoorString = mapCoorString.substring(1, mapCoorString.length() - 1);

			String[] xyCoor = mapCoorString.split(",");

			if (xyCoor.length > 1){
				Integer xPos = Integer.valueOf(xyCoor[0]);
				Integer yPos = Integer.valueOf(xyCoor[1]);

				c = new MapCoordinates(xPos, yPos);
			}
		}

		return c;
	}

	private String convertMapCoordinatesToString(MapCoordinates c){
		StringBuffer strCoor = new StringBuffer();

		if (c != null){
			strCoor.append("(");
			strCoor.append(c.getX());
			strCoor.append(",");
			strCoor.append(c.getY());
			strCoor.append(")");
		}

		return strCoor.toString();
	}

	@Override
	public boolean updateElementToDB(Cache c, Object newKey,
			Cacheable newElement) {
		// TODO Auto-generated method stub
		return this.addElementToDB(c, newKey, newElement);
	}

}
